/**
 * 用于写Promise的测试函数
 */

const { resolve } = require('./myPromise');
const MyPromise = require('./myPromise')

run();

//执行当前的测试函数
function run() {
    // normal()
    // test1(); //基础逻辑
    // test2();//测试异步逻辑
    // test3();//测试then多次调用
    // test3_async();//测试then多次调用
    // test4();//then方法链式调用，
    // test4_p();//then方法链式调用
    // normal2();//系统promise的链式返回自己
    // test5();//链式返回自己
    // test6(); //执行函数异常，或者then中异常
    // test7();//rejected情况处理
    // test8();//处理异步执行的情况
    // test9();//then可选值的情况
    // test10();//MyPromose.all
    // test11();//MyPromise.resolve
    // test12(); //增加finally方法
    test13();//增加catch方法
}

 /**
  * 正常promise的使用
  */
function normal() {
    const p = new Promise((resolve,reject)=>{
        resolve('0 成功')
    })

    p.then(v=>{
        console.log('success',v)
    },r=>{
        console.log('fail',r)
    })
}

//链式调用返回自己
//提示错误：‘TypeError: Chaining cycle detected for promise #<Promise>’
function normal2() {
    const p = new Promise((resolve,reject)=>{
        resolve('0 成功')
    })

    const p2 = p.then(v=>{
        console.log('success',v)
        return p2
    },r=>{
        console.log('fail',r)
    })

    //如果没有下面继续，node环境，控制台打印错误

    p2.then(v=>{
        console.log('success2',v)
    },r=>{ //这里可以捕捉到错误 ‘TypeError: Chaining cycle detected for promise #<Promise>’
        console.log('fail2',r)
    })
}

//1. promise是一个类，构造函数，需要传入一个执行函数
//2. 拥有then函数，then函数有两个参数，一个成功回调，一个失败回调
//3. promise 有三种状态：pending(初始状态)、fulfilled、rejected，状态单向改变(pending->fulfilled,pending->rejected)，一旦确定不能再次改变
function test1() {
    const p = new MyPromise((resolve,reject)=>{
        resolve('0 成功')
        // reject('0 fail')
    })

    p.then(v=>{
        console.log('success',v)
    },r=>{
        console.log('fail',r)
    })
}

//4. 加入异步处理逻辑
function test2() {
    const p = new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            // resolve('0 成功')
            reject('0 fail')
        },2000)
    })

    p.then(v=>{
        console.log('success',v)
    },r=>{
        console.log('fail',r)
    })
}

//5. then可以被多次调用 ， 每个then都会被回调
//目前如果promise内部只是同步调用,没问题，但异步，就只会回调最后一次，需要将多个回调进行缓存
function test3() {

    const p = new MyPromise((resolve,reject)=>{
        resolve('0 成功')
        // reject('0 fail')
    })

    p.then(v=>{
        console.log('success',v)
    },r=>{
        console.log('fail',r)
    })

    p.then(v=>{
        console.log('success2',v)
    },r=>{
        console.log('fail2',r)
    })
}

//then方法多次调用，异步方法
function test3_async() {
    const p = new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('0 成功')
            // reject('0 fail')
        },2000)
    })

    p.then(v=>{
        console.log('success',v)
    },r=>{
        console.log('fail',r)
    })

    p.then(v=>{
        console.log('success2',v)
    },r=>{
        console.log('fail2',r)
    })
}

//6. then方法的链式调用
// then方法每次返回一个新的promise对象，才能实现链式调用
// 新对象的值等于回调函数的返回值
function test4() {
    const p = new MyPromise((resolve,reject)=>{
        resolve('0 成功')
        // reject('0 fail')
    })

    p.then(v=>{
        console.log('success',v)
        return '1 成功'
    },r=>{
        console.log('fail',r)
    }).then(v=>{
        console.log('success2',v)
    },r=>{
        console.log('fail',r)
    })
}

function test4_p() {
    const p = new MyPromise((resolve,reject)=>{
        resolve('0 成功')
        // reject('0 fail')
    })

    p.then(v=>{
        console.log('success',v)
        return new MyPromise((resolve,reject)=>{
            resolve('success1-p 成功')
        })
    },r=>{
        console.log('fail',r)
    }).then(v=>{
        console.log('success2',v)
    },r=>{
        console.log('fail',r)
    })
}

//7.链式调用返回自己
//没处理前直接异常：ReferenceError: Cannot access 'p2' before initialization
//并且p2.then也捕捉不到错误
function test5() {
    const p = new MyPromise((resolve,reject)=>{
        resolve('0 成功')
        // reject('0 fail')
    })

    const p2 = p.then(v=>{
        console.log('success',v)
        return p2
    },r=>{
        console.log('fail',r)
    })

    p2.then(v=>{
        console.log('success2',v)
    },r=>{ 
        console.log('fail2类型',typeof r)
        console.log('fail2',r.message) //这里有疑问？？？，同样代码游览器执行，就可以直接打印r，没有加message
    })
}

//8.promise的执行函数发生异常
//需要在失败回调中可以捕捉到
function test6() {
    const p = new MyPromise((resolve,reject)=>{
        // throw new Error('我出错了')
        resolve('0 成功')
    })
    p.then(v=>{
        console.log('success',v)
        throw new Error('then error')
        return '1 成功'
    },r=>{
        console.log('fail',r)
    }).then(v=>{
        console.log('success1:',v)
    },r=>{
        console.log('fail1:',r)
    })
}

//9.promise 的失败的情况处理
function test7() {
    const p = new MyPromise((resolve,reject)=>{
        reject('0 fail')
    })
    p.then(v=>{
        console.log('success',v)
        throw new Error('then error')
        return '1 成功'
    },r=>{
        console.log('fail',r)
        throw new Error('fail error')
        return '1 fail'
    }).then(v=>{
        console.log('success1:',v)
    },r=>{
        console.log('fail1:',r)
    })
}

//10.异步的情况处理
function test8() {
    const p = new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('0 成功')
            // reject('0 fail')
        },2000)
    })
    p.then(v=>{
        console.log('success',v)
        // throw new Error('then error')
        // return '1 成功'
        return new MyPromise((resolve,reject)=>{
            // resolve('1-p 成功')
            setTimeout(()=>{
                resolve('1-p 异步成功')
            },3000)
        })
    },r=>{
        console.log('fail',r)
        // throw new Error('fail error')
        return '1 fail'
    }).then(v=>{
        console.log('success1:',v)
    },r=>{
        console.log('fail1:',r)
    })
}

//11.then的参数都是可选参数 ， 如果未填写，将结果继续往下传，相当于(v) => v 
// 没处理前：会先报failCallback 异常，再报 successCallback异常
function test9() {
    const p = new MyPromise((resolve,reject)=>{
        // resolve('0 succ')
        // reject('0 fail')
        setTimeout(()=>{
            resolve('0 succ')
        },1000)
    })
    p.then()
    .then()
    .then(v=>{
        console.log('success',v);
    },r=>{
        console.log('fail',r)
    })
}

//12. 实现Promise.all , 可以将多个异步，按顺序返回
function test10() {
    const p1 = new MyPromise((resolve,reject)=>{
        resolve('p1')
    })

    const p2 = new MyPromise((resolve,reject)=>{
        resolve('p2')
        reject('p2 fail')
    })

    MyPromise.all(['a','b',p1,p2,'c']).then(v=>{
        console.log('success',v)
    },r=>{
        console.log('fail',r)
    })
}

//13. 实现resolve方法,  需要特殊处理传入Promise的情况 ,直接返回该promise对象，而不是新建一个
function test11() {
    MyPromise.resolve('123').then(v=>{
        console.log('success',v)
    })

    const p1 = new MyPromise((resolve,reject)=>{
        resolve('p1')
    })
    MyPromise.resolve(p1).then(v=>{
        console.log('success1',v)
    },r=>{
        console.log('fail1',r)
    })
}

//14.实现finally实例方法
function test12() {
    new MyPromise((resolve,reject)=>{
        resolve('p')
    }).then(v=>{
        console.log('then',v)
        return '123'
    },r=>{
        console.log('error',r)
    }).finally(()=>{
        console.log('finally')
        return new MyPromise((resolve,reject)=>{
            setTimeout(()=>{
                resolve('456')
            },1000)
        })
    }).then(v=>{
        console.log('then1',v)
    },r=>{
        console.log('error1',r)
    })
}

//15.增加catch方法
function test13() {
    new MyPromise((resolve,reject)=>{
        // resolve('0 成功')
        reject('0 fail')
    }).then(v=>{
        console.log('suc',v)
    }).catch(e=>{
        console.log('fail',e)
        return '1 成功'
    }).then(v=>{
        console.log('then2',v)
    })
}